#include <stdint.h>

#include "tErreur.h"
#include "packet_factory.h"
#include "comm.h"
#include "tJournal.h"

/* Raise an error : create the structure then post it into the FIFO */
void raise_error( int8_t code )
{
	raise_error_with_parameter( code, 0 );
}

/* Alternative case where a param is needed */
void raise_error_with_parameter( int8_t code, int16_t param )
{
	ERROR_DATA err;
		
	err.code 	  = code;
	err.parameter = param;
		
	msgQSend( msg_error, (char*) &err, sizeof(err), WAIT_FOREVER, 0 );	
}

/* tErreur task routine */
void tErreur()
{
	ERROR_DATA error;
	PACKET_HDR* packet;
	PACKET_TYPE type;
	int8_t mustStop;
	
	msg_error = msgQCreate( 32, sizeof(ERROR_DATA), MSG_Q_FIFO );
	
	/* Run until mustStop is set to 1 (STOP packet received) OR
	 * if Mere task asks to stop running now. */
	mustStop = 0;
	while( mustStop == 0 && msgQNumMsgs( msg_extinction ) == 0 )
	{
		char buffer[64];
		STATUS res;
		
		/* Wait until there is another error to handle */
		res = msgQReceive( msg_error, (char*) &error, sizeof(error), WAIT_FOREVER );

		printf( "ERROR CODE : %d [%d]\n", error.code, res );
		
		/* Check the error validity */
		if( error.code >= ERR_FIRST_CODE && error.code <= ERR_LAST_CODE )
		{
			/* Something wrong happened !
			 * Raise an error to the supervisor but the code is fixed to UNDETERMINED !
			 */			
			error.parameter = error.code;
			error.code = ERR_UNDETERMINED;
		}
		
		/* Suspend new pieces */
		semTake( semClapet, WAIT_FOREVER );
		clapet = 1;
		semGive( semClapet );

		sprintf( buffer, "An error has been raised. (CODE = %d; PARAM: %d)", error.code, error.parameter );
		add_log( LOG_TYPE_ERROR, "tError", buffer );
		
		/* 
		 * Notify supervisor that an error occurs and wait its answer :
		 * Must the system restart or shutdown ?
		 */
		packet = (PACKET_HDR*) create_packet_error( error.code, error.parameter );
		send_packet( packet );
		free( packet );
		
		do
		{
			type = recv_packet( TASK_ERROR, (char*) packet ); /* char !! */
		} while( type != PACKET_START || type != PACKET_STOP );
		
		/* If we got a START packet, we can resume */
		if( type == PACKET_START )
		{
			/* Resume pieces flow */
			semTake( semClapet, WAIT_FOREVER );
			clapet = 0;
			semGive( semClapet );
			
			add_log( LOG_TYPE_ERROR, "tError", "Supervisor decided to resume execution." );
		}
		/* A STOP packet stops the application. */
		else if( type == PACKET_STOP )
		{
			mustStop = 1;
			
			add_log( LOG_TYPE_ERROR, "tError", "Supervisor decided to shutdown application." );
		}
	}
	
	msgQDelete( msg_error );

	exit( 0 );
}
